/****************************************************************************
*
* Copyright (c) 2023  C*Core -   All Rights Reserved
*
* THIS SOFTWARE IS DISTRIBUTED "AS IS, " AND ALL WARRANTIES ARE DISCLAIMED,
* INCLUDING MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* PROJECT     : CCFC2011BC
* DESCRIPTION : ADC demo code
* HISTORY     : Initial version.
* @file     adc_demo.c
* @version  1.1
* @date     2023 - 02 - 20
* @brief    Initial version.
*
*****************************************************************************/
#include "adc_demo.h"
#include "adc_lld.h"
#include "console.h"
#include "CCFC2011BC.h"
#include "Mcu_lld.h"
#include "IntcInterrupts.h"
#include "intc_lld.h"
#include "edma_lld.h"
#include "sys.h"

static uint32_t case1_ADC0Buf[4] = {0}; /* PRQA S 3218 */
static uint32_t case1_ADC1Buf[4] = {0}; /* PRQA S 3218 */
static uint32_t case2_ADC0Buf[4] = {0}; /* PRQA S 3218 */
static uint32_t case2_ADC1Buf[4] = {0}; /* PRQA S 3218 */
static uint32_t case3_ADC0Buf[4] = {0}; /* PRQA S 3218 */
static uint32_t case3_ADC1Buf[4] = {0}; /* PRQA S 3218 */
static uint32_t case5_ADC0Buf[5] = {0}; /* PRQA S 3218 */
static uint32_t case5_ADC1Buf[4] = {0}; /* PRQA S 3218 */
static uint32_t case6_ADC0Buf[4] = {0}; /* PRQA S 3218, 3678 */
static uint32_t case6_ADC1Buf[4] = {0}; /* PRQA S 3218, 3678 */
static uint32_t case7_ADC0Buf[4] = {0}; /* PRQA S 3218 */
static uint32_t case7_ADC1Buf[4] = {0}; /* PRQA S 3218 */

static ADC_Driver ADC0_driver;
static ADC_Driver ADC1_driver;

/*******************************************************************************
 * @brief      ADC0_EOC_InterruptHandler
 *             This function shall be the ADC0 Interrupt handler.
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void ADC0_EOC_InterruptHandler(void)
{
    uint32_t i;
    uint32_t temp;
    uint32_t channel;

    temp = ADC_0.ISR.R;
    channel = ADC_0.CEOCFR0.R;

    if ((temp & ISR_EOCTU) != 0U)
    {
        ADC_0.ISR.R |= ISR_EOCTU;
        /* do something */
    }
    if ((temp & ISR_JEOC) != 0U)
    {
        ADC_0.ISR.R |= ISR_JEOC;
        /* do something */
    }
    if ((temp & ISR_JECH) != 0U)
    {
        ADC_0.ISR.R |= ISR_JECH;
        /* do something */
    }
    if ((temp & ISR_EOC) != 0U)
    {
        ADC_0.ISR.R |= ISR_EOC;
        PSPRINTF("\n ADC0 EOC INTERRUPU\n");
        /* do something */
    }

    if ((temp & ISR_ECH) != 0U)
    {
        ADC_0.ISR.R |= ISR_ECH;
        PSPRINTF("\n ADC0 ECH IRQ\n");
        for (i = 0U; i < 4U; i++)
        {
            /* Ch0~Ch3 */
            case3_ADC0Buf[i] = ADC_LLD_ChanValue(&ADC0_driver, i);
        }
        ADC_Stop(&ADC0_driver);
    }
    ADC_0.CEOCFR0.R = channel;
}

/*******************************************************************************
 * @brief      ADC1_EOC_InterruptHandler
 *             This function shall be the ADC1 Interrupt handler.
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void ADC1_EOC_InterruptHandler(void)
{
    uint32_t i;
    uint32_t temp;
    uint32_t channel;

    temp = ADC_1.ISR.R;
    channel = ADC_1.CEOCFR0.R;

    if ((temp & ISR_EOCTU) != 0U)
    {
        ADC_1.ISR.R |= ISR_EOCTU;
        /* do something */
    }
    if ((temp & ISR_JEOC) != 0U)
    {
        ADC_1.ISR.R |= ISR_JEOC;
        /* do something */
    }
    if ((temp & ISR_JECH) != 0U)
    {
        ADC_1.ISR.R |= ISR_JECH;
        /* do something */
    }
    if ((temp & ISR_EOC) != 0U)
    {
        ADC_1.ISR.R |= ISR_EOC;
        PSPRINTF("\n ADC1 EOC INTERRUPU\n");
    }

    if ((temp & ISR_ECH) != 0U)
    {
        ADC_1.ISR.R |= ISR_ECH;
        PSPRINTF("\n ADC1 ECH IRQ\n");
        for (i = 32U; i < 36U; i++)
        {
            /* Ch32~Ch35 */
                case3_ADC1Buf[i - 32U] = ADC_LLD_ChanValue(&ADC1_driver, i);
        }
        ADC_Stop(&ADC1_driver);
    }
    ADC_1.CEOCFR0.R = channel;
}

/*******************************************************************************
 * @brief      ADC0_WDG_InterruptHandler
 *             This function shall be the ADC0 WDG Interrupt handler.
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void ADC0_WDG_InterruptHandler(void)
{
    uint32_t temp;

    temp = ADC_0.WTISR.R;
    
    if (((temp & 0x800U) | (temp & 0x400U)) != 0U)
    {
        ADC_0.WTISR.R |= 0xc00U;
        PSPRINTF("\n ADC0 data is out of range:0x%x", temp);
    }

    if (((temp & 0x200U) | (temp & 0x100U)) != 0U)
    {
        ADC_0.WTISR.R |= 0x300U;
        PSPRINTF("\n ADC0 data is out of range:0x%x", temp);
    }

    if (((temp & 0x080U) | (temp & 0x040U)) != 0U)
    {
        ADC_0.WTISR.R |= 0x0c0U;
        PSPRINTF("\n ADC0 data is out of range:0x%x", temp);
    }

    if (((temp & 0x020U) | (temp & 0x010U)) != 0U)
    {
        ADC_0.WTISR.R |= 0x30U;
        PSPRINTF("\n ADC0 data is out of range:0x%x", temp);
    }

    if (((temp & 0x08U) | (temp & 0x04U)) != 0U)
    {
        ADC_0.WTISR.R |= 0x0cU;
        PSPRINTF("\n ADC0 data is out of range:0x%x", temp);
    }

    if (((temp & 0x02U) | (temp & 0x01U)) != 0U)
    {
        ADC_0.WTISR.R |= 0x03U;
        PSPRINTF("\n ADC0 data is out of range:0x%x", temp);
    }
    
    PSPRINTF("\nTEST PASS ! ! Please make the ADC value out of Threshold to exit the interrupt");

    
//    ADC_0.WTIMR.R = 0U;
}

/*******************************************************************************
 * @brief      ADC1_WDG_InterruptHandler
 *             This function shall be the ADC1 WDG Interrupt handler.
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void ADC1_WDG_InterruptHandler(void)
{
    uint32_t temp;

    temp = ADC_1.WTISR.R;

    if (((temp & 0x20U) | (temp & 0x10U)) != 0U)
    {
        ADC_1.WTISR.R |= 0x30U;
        PSPRINTF("\n ADC1 data is out of range:0x%x", temp);
    }

    if (((temp & 0x08U) | (temp & 0x04U)) != 0U)
    {
        ADC_1.WTISR.R |= 0x0cU;
        PSPRINTF("\n ADC1 data is out of range:0x%x", temp);
    }

    if (((temp & 0x02U) | (temp & 0x01U)) != 0U)
    {
        ADC_1.WTISR.R |= 0x03U;
        PSPRINTF("\n ADC1 data is out of range:0x%x", temp);
    }

//    ADC_1.WTIMR.R = 0U;
}

static struct WDG_struct WDG_config = /* PRQA S 3218 */
{
		
    {1000,1000,1000,1000},		//High threshold value 0~1023
    {0,0,0,0},			  		//Low threshold value 0~1023
    {0,1,2,3},			  		//Channel Select
    {TRUE,TRUE,TRUE,TRUE},		//Channel Enable
};

static ADC_Config usr_scan_config =
{
    ADC_OWREN,
    ADC_RIGHTALIGNED,
    ADC_MODE_SCAN,
    ADC_ADCLKSEL_0,
    ADC_ACKO,
    ADC_PWDN
};

static ADC_Config usr_oneshot_config =
{
    ADC_OWREN,
    ADC_RIGHTALIGNED,
    ADC_MODE_ONESHOT,
    ADC_ADCLKSEL_0,
    ADC_ACKO,
    ADC_PWDN
};

/*******************************************************************************
 * @brief      ADC Test Case1: ADC scan mode
 * @param[in]  ExInputMv: 0~5000(mV)
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void ADC_Test_Case1_ScanMode(uint16_t ExInputMv)/* PRQA S 3219 */
{
    uint32_t i;
    uint32_t ret = 0U;
    uint16_t adc0_expectCData;
    uint16_t adc1_expectCData;

    adc0_expectCData = ExInputMv * ADC0_10BIT / ADC_POWER_REF;
    adc1_expectCData = ExInputMv * ADC1_12BIT / ADC_POWER_REF;

    ADC0_driver.index = ADC0_SELECT;
    ADC1_driver.index = ADC1_SELECT;

    ADC_LLD_Cfg_Init(&ADC0_driver, &usr_scan_config);
    ADC_LLD_Cfg_Init(&ADC1_driver, &usr_scan_config);

    for (i = 0U; i < 4U; i++)
    {
        /* Ch0~Ch3 */
        ADC_LLD_ChannelConfig(&ADC0_driver, i);
    }
    for (i = 32U; i < 36U; i++)
    {
        /* Ch32~Ch35 */
        ADC_LLD_ChannelConfig(&ADC1_driver, i);
    }

    ADC_LLD_ConversionTiming(&ADC0_driver, ADC_CTR0_CH0_CH15, CTR_INPCMP_5, CTR_INPSAMP(60UL)); /* PRQA S 3469 */
    ADC_LLD_ConversionTiming(&ADC1_driver, ADC_CTR1_CH32_CH59, CTR_INPCMP_5, CTR_INPSAMP(60UL)); /* PRQA S 3469 */

    delay_ms(1U);

    ADC_LLD_Start(&ADC0_driver);
    ADC_LLD_Start(&ADC1_driver);

    while (ADC_ECH_IntFlag(&ADC0_driver) != 1U)
    {
        ;
    }
    while (ADC_ECH_IntFlag(&ADC1_driver) != 1U)
    {
        ;
    }

    for (i = 0U; i < 4U; i++)
    {
        /* Ch0~Ch3 */
        case1_ADC0Buf[i] = ADC_LLD_ChanValue(&ADC0_driver, i);
    }
    for (i = 32U; i < 36U; i++)
    {
        /* Ch32~Ch35 */
        case1_ADC1Buf[i - 32U] = ADC_LLD_ChanValue(&ADC1_driver, i);
    }

    ADC_Stop(&ADC0_driver);
    ADC_Stop(&ADC1_driver);

    PSPRINTF("\n || ***********************\n");
    for (i = 0U; i < 4U; i++)
    {
        PSPRINTF(" ADC0 Ch%d data = %d, = %dmV, ", i, case1_ADC0Buf[i], \
                case1_ADC0Buf[i]*ADC_POWER_REF/ADC0_10BIT);
        if (case1_ADC0Buf[i] > adc0_expectCData)
        {
            if ((case1_ADC0Buf[i] - adc0_expectCData) <= 5U)
            {
                PSPRINTF("Pass!\n");
            }
            else
            {
                ret++;
                PSPRINTF("Fail(Input:%d, %dmV)!\n", adc0_expectCData, ExInputMv);
            }
        }
        else
        {
            if ((adc0_expectCData - case1_ADC0Buf[i]) <= 5U)
            {
                PSPRINTF("Pass!\n");
            }
            else
            {
                ret++;
                PSPRINTF("Fail(Input:%d, %dmV)!\n", adc0_expectCData, ExInputMv);
            }
        }
    }
    for (i = 32U; i < 36U; i++)
    {
        PSPRINTF(" ADC1 Ch%d data = %d, = %dmV, ", i, case1_ADC1Buf[i - 32U], \
                case1_ADC1Buf[i - 32U]*ADC_POWER_REF/ADC1_12BIT);
        if (case1_ADC1Buf[i - 32U] > adc1_expectCData)
        {
            if ((case1_ADC1Buf[i - 32U] - adc1_expectCData) <= 5U)
            {
                PSPRINTF("Pass!\n");
            }
            else
            {
                ret++;
                PSPRINTF("Fail(Input:%d, %dmV)!\n", adc1_expectCData, ExInputMv);
            }
        }
        else
        {
            if ((adc1_expectCData - case1_ADC1Buf[i - 32U]) < 5U)
            {
                PSPRINTF("Pass!\n");
            }
            else
            {
                ret++;
                PSPRINTF("Fail(Input:%d, %dmV)!\n", adc1_expectCData, ExInputMv);
            }
        }
    }

    if (ret != 0U)
    {
        PSPRINTF("\n ADC_Test_Case1_ScanMode Fail!\n");
    }
    else
    {
        PSPRINTF("\n ADC_Test_Case1_ScanMode Pass!\n");
    }
    PSPRINTF("\n*********************** || \n");
}

/*******************************************************************************
 * @brief      ADC Test Case2: ADC oneshot mode
 * @param[in]  ExInputMv: 0~5000(mV)
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void ADC_Test_Case2_OneshotMode(uint16_t ExInputMv)/* PRQA S 3219 */
{
    uint32_t i;
    uint32_t ret = 0U;
    uint16_t adc0_expectCData;
    uint16_t adc1_expectCData;

    adc0_expectCData = ExInputMv * ADC0_10BIT / ADC_POWER_REF;
    adc1_expectCData = ExInputMv * ADC1_12BIT / ADC_POWER_REF;

    ADC0_driver.index = ADC0_SELECT;
    ADC1_driver.index = ADC1_SELECT;

    ADC_LLD_Cfg_Init(&ADC0_driver, &usr_oneshot_config);
    ADC_LLD_Cfg_Init(&ADC1_driver, &usr_oneshot_config);

    for (i = 0U; i < 4U; i++)
    {
        /* Ch0~Ch3 */
        ADC_LLD_ChannelConfig(&ADC0_driver, i);
    }
    for (i = 32U; i < 36U; i++)
    {
        /* Ch32~Ch35 */
        ADC_LLD_ChannelConfig(&ADC1_driver, i);
    }

    ADC_LLD_ConversionTiming(&ADC0_driver, ADC_CTR0_CH0_CH15, CTR_INPCMP_5, CTR_INPSAMP(60UL)); /* PRQA S 3469 */
    ADC_LLD_ConversionTiming(&ADC1_driver, ADC_CTR1_CH32_CH59, CTR_INPCMP_5, CTR_INPSAMP(60UL)); /* PRQA S 3469 */

    delay_ms(1U);

    ADC_LLD_Start(&ADC0_driver);
    ADC_LLD_Start(&ADC1_driver);

    while (ADC_ECH_IntFlag(&ADC0_driver) != 1U)
    {
        ;
    }
    while (ADC_ECH_IntFlag(&ADC1_driver) != 1U)
    {
        ;
    }

    for (i = 0U; i < 4U; i++)
    {
        /* Ch0~Ch3 */
        case2_ADC0Buf[i] = ADC_LLD_ChanValue(&ADC0_driver, i);
    }
    for (i = 32U; i < 36U; i++)
    {
        /* Ch32~Ch35 */
        case2_ADC1Buf[i - 32U] = ADC_LLD_ChanValue(&ADC1_driver, i);
    }

    ADC_Stop(&ADC0_driver);
    ADC_Stop(&ADC1_driver);

    PSPRINTF("\n || ***********************\n");
    for (i = 0U; i < 4U; i++)
    {
        PSPRINTF(" ADC0 Ch%d data = %d, = %dmV, ", i, case2_ADC0Buf[i], \
                case2_ADC0Buf[i]*ADC_POWER_REF/ADC0_10BIT);
        if (case2_ADC0Buf[i] > adc0_expectCData)
        {
            if ((case2_ADC0Buf[i] - adc0_expectCData) <= (20U * ADC0_10BIT / ADC_POWER_REF))
            {/* < 20mv */
                PSPRINTF("Pass!\n");
            }
            else
            {
                ret++;
                PSPRINTF("Fail(Input:%d, %dmV)!\n", adc0_expectCData, ExInputMv);
            }
        }
        else
        {
            if ((adc0_expectCData - case2_ADC0Buf[i]) <= (20U * ADC0_10BIT / ADC_POWER_REF))
            {/* < 20mv */
                PSPRINTF("Pass!\n");
            }
            else
            {
                ret++;
                PSPRINTF("Fail(Input:%d, %dmV)!\n", adc0_expectCData, ExInputMv);
            }
        }
    }
    for (i = 32U; i < 36U; i++)
    {
        PSPRINTF(" ADC1 Ch%d data = %d, = %dmV, ", i, case2_ADC1Buf[i - 32U], \
                case2_ADC1Buf[i - 32U]*ADC_POWER_REF/ADC1_12BIT);
        if (case2_ADC1Buf[i - 32U] > adc1_expectCData)
        {
            if ((case2_ADC1Buf[i - 32U] - adc1_expectCData) <= (20U * ADC1_12BIT / ADC_POWER_REF))
            {/* < 20mv */
                PSPRINTF("Pass!\n");
            }
            else
            {
                ret++;
                PSPRINTF("Fail(Input:%d, %dmV)!\n", adc1_expectCData, ExInputMv);
            }
        }
        else
        {
            if ((adc1_expectCData - case2_ADC1Buf[i - 32U]) <= (20U * ADC1_12BIT / ADC_POWER_REF))
            {/* < 20mv */
                PSPRINTF("Pass!\n");
            }
            else
            {
                ret++;
                PSPRINTF("Fail(Input:%d, %dmV)!\n", adc1_expectCData, ExInputMv);
            }
        }
    }

    if (ret != 0U)
    {
        PSPRINTF("\n ADC_Test_Case2_OneshotMode Fail!\n");
    }
    else
    {
        PSPRINTF("\n ADC_Test_Case2_OneshotMode Pass!\n");
    }
    PSPRINTF("\n*********************** || \n");
}

/*******************************************************************************
 * @brief      ADC Test Case3: ADC ECH interrupt
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void ADC_Test_Case3_ECHInt(void)/* PRQA S 3219 */
{
    uint32_t i = 0;

    INTC_IRQ_Enable();

    ADC0_driver.index = ADC0_SELECT;
    ADC1_driver.index = ADC1_SELECT;

    /* ADC0 interrupt init */
    INTC_InstallINTCInterruptHandler(ADC0_EOC_InterruptHandler, (uint16_t)ADC0_EOC_IRQn, (uint8_t)PSR_PRI_11);

    /* ADC1 interrupt init */
    INTC_InstallINTCInterruptHandler(ADC1_EOC_InterruptHandler, (uint16_t)ADC1_EOC_IRQn, (uint8_t)PSR_PRI_11);

    ADC_LLD_Cfg_Init(&ADC0_driver, &usr_scan_config);
    ADC_LLD_Cfg_Init(&ADC1_driver, &usr_scan_config);

    for (i = 0U; i < 4U; i++)
    {
        /* Ch0~Ch3 */
        ADC_LLD_ChannelConfig(&ADC0_driver, i);
    }
    for (i = 32U; i < 36U; i++)
    {
        /* Ch32~Ch35 */
        ADC_LLD_ChannelConfig(&ADC1_driver, i);
    }

    ADC_LLD_ConversionTiming(&ADC0_driver, ADC_CTR0_CH0_CH15, CTR_INPCMP_5, CTR_INPSAMP(60UL)); /* PRQA S 3469 */
    ADC_LLD_ConversionTiming(&ADC1_driver, ADC_CTR1_CH32_CH59, CTR_INPCMP_5, CTR_INPSAMP(60UL)); /* PRQA S 3469 */

    ADC_LLD_IntcConfig(&ADC0_driver, IMR_MASK_ECH|IMR_MASK_EOC);
    ADC_LLD_IntcConfig(&ADC1_driver, IMR_MASK_ECH|IMR_MASK_EOC);

    delay_ms(1U);

    ADC_LLD_Start(&ADC0_driver);
    ADC_LLD_Start(&ADC1_driver);

    PSPRINTF("\n***********************\n");
    PSPRINTF("ADC_Test_Case3_ECHInt Start!\n");
    for (i = 0U; i < 4U; i++)
    {
        PSPRINTF("ADC0 Ch%d data = %d, = %dmV\n", i, case3_ADC0Buf[i], \
                case3_ADC0Buf[i]*ADC_POWER_REF/0x3FFU);
    }
    for (i = 32U; i < 36U; i++)
    {
        PSPRINTF("ADC1 Ch%d data = %d, = %dmV\n", i, case3_ADC1Buf[i - 32U], \
                case3_ADC1Buf[i - 32U]*ADC_POWER_REF/0xFFFU);
    }
    PSPRINTF("ADC_Test_Case3_ECHInt End!\n");
    PSPRINTF("***********************\n\n");
}

/*******************************************************************************
 * @brief      ADC Test Case1: ADC scan mode
 * @param[in]  ExInputMv: 0~5000(mV)
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void ADC_Test_Case4_WtgInt(void)/* PRQA S 3219 */
{
    uint32_t i = 0;

    INTC_IRQ_Enable();

    ADC0_driver.index = ADC0_SELECT;
    ADC0_driver.WDG_t = &WDG_config;
    
    /* ADC0 interrupt init */
    INTC_InstallINTCInterruptHandler(ADC0_EOC_InterruptHandler, (uint16_t)ADC0_EOC_IRQn, (uint8_t)PSR_PRI_11);
    INTC_InstallINTCInterruptHandler(ADC0_WDG_InterruptHandler, (uint16_t)ADC0_WD_IRQn, (uint8_t)PSR_PRI_12);

    ADC_LLD_Cfg_Init(&ADC0_driver, &usr_scan_config);


    for (i = 0U; i < 4U; i++)
    {
        /* Ch0~Ch3 */
        ADC_LLD_ChannelConfig(&ADC0_driver, i);
    }

	ADC_LLD_ConversionTiming(&ADC0_driver, ADC_CTR0_CH0_CH15, CTR_INPCMP_5, CTR_INPSAMP(60UL)); /* PRQA S 3469 */
	ADC_LLD_Start(&ADC0_driver);
	
	ADC_LLD_WDGInit(&ADC0_driver);
	
	
	while(1)
	{
		for (i = 0U; i < 4U; i++)
		{
			/* Ch0~Ch3 */
			case1_ADC0Buf[i] = ADC_LLD_ChanValue(&ADC0_driver, i);
		}


		PSPRINTF("\r\n");
		for (i = 0U; i < 4U; i++)
		{
			PSPRINTF("ADC0 Ch%d = %d	", i, case1_ADC0Buf[i], \
					case1_ADC0Buf[i]*ADC_POWER_REF/ADC0_10BIT);
		}
		

		delay_ms(1000);
	}
//    ADC_Stop(&ADC0_driver);
//    ADC_Stop(&ADC1_driver);
}

/*******************************************************************************
 * @brief      ADC Test Case5: ADC Injected Mode
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void ADC_Test_Case5_InjectedMode(void)/* PRQA S 3219 */
{
    uint32_t i = 0;

    INTC_IRQ_Disable();

    ADC0_driver.index = ADC0_SELECT;
    ADC1_driver.index = ADC1_SELECT;

    ADC_LLD_Cfg_Init(&ADC0_driver, &usr_oneshot_config);
    ADC_LLD_Cfg_Init(&ADC1_driver, &usr_oneshot_config);

    for (i = 0U; i < 4U; i++)
    {
        /* Ch0~Ch3 */
        ADC_LLD_ChannelConfig(&ADC0_driver, i);
    }
    for (i = 32U; i < 36U; i++)
    {
        /* Ch32~Ch35 */
        ADC_LLD_ChannelConfig(&ADC1_driver, i);
    }

    ADC_LLD_ConversionTiming(&ADC0_driver, ADC_CTR0_CH0_CH15, CTR_INPCMP_5, CTR_INPSAMP(60UL)); /* PRQA S 3469 */
    ADC_LLD_ConversionTiming(&ADC1_driver, ADC_CTR1_CH32_CH59, CTR_INPCMP_5, CTR_INPSAMP(60UL)); /* PRQA S 3469 */

    delay_ms(1U);

    ADC_LLD_Start(&ADC0_driver);
    ADC_LLD_Start(&ADC1_driver);

    while (ADC_ECH_IntFlag(&ADC0_driver) != 1U)
    {
        ;
    }
    while (ADC_ECH_IntFlag(&ADC1_driver) != 1U)
    {
        ;
    }

    for (i = 0U; i < 4U; i++)
    {
        /* Ch0~Ch3 */
        case5_ADC0Buf[i] = ADC_LLD_ChanValue(&ADC0_driver, i);
    }
    for (i = 32U; i < 36U; i++)
    {
        /* Ch32~Ch35 */
        case5_ADC1Buf[i - 32U] = ADC_LLD_ChanValue(&ADC1_driver, i);
    }

    /* Ch4 */
    ADC_LLD_InjectedChannelConfig(&ADC0_driver, 4);
    ADC_LLD_InjectedStart(&ADC0_driver);

    while (ADC_JECH_IntFlag(&ADC0_driver) != 1U)
    {
        ;
    }
    case5_ADC0Buf[4] = ADC_LLD_ChanValue(&ADC0_driver, 4);

    ADC_Stop(&ADC0_driver);
    ADC_Stop(&ADC1_driver);

    PSPRINTF("\n***********************\n");
    PSPRINTF("ADC_Test_Case5_InjectedMode Start!\n");
    for (i = 0U; i < (4U + 1U); i++)
    {
        PSPRINTF("ADC0 Ch%d data = %d, = %dmV\n", i, case5_ADC0Buf[i], \
                case5_ADC0Buf[i]*ADC_POWER_REF/0x3FFU);
    }
    for (i = 32U; i < 36U; i++)
    {
        PSPRINTF("ADC1 Ch%d data = %d, = %dmV\n", i, case5_ADC1Buf[i - 32U], \
                case5_ADC1Buf[i - 32U]*ADC_POWER_REF/0xFFFU);
    }
    PSPRINTF("ADC_Test_Case5_InjectedMode End!\n");
    PSPRINTF("***********************\n\n");
}

/*******************************************************************************
 * @brief      ADC Test Case6: ADC DMA Mode
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void ADC_Test_Case6_DMA(void)/* PRQA S 3219 */
{
    uint32_t i = 0;

    INTC_IRQ_Enable();

    ADC0_driver.index = ADC0_SELECT;
    ADC1_driver.index = ADC1_SELECT;

    ADC_LLD_Cfg_Init(&ADC0_driver, &usr_scan_config);
    ADC_LLD_Cfg_Init(&ADC1_driver, &usr_scan_config);

    for (i = 0U; i < 4U; i++)
    {
        /* Ch0~Ch3 */
        ADC_LLD_ChannelConfig(&ADC0_driver, i);
        ADC_LLD_DMAChannelConfig(&ADC0_driver, i);
    }
    for (i = 32U; i < 36U; i++)
    {
        /* Ch32~Ch35 */
        ADC_LLD_ChannelConfig(&ADC1_driver, i);
        ADC_LLD_DMAChannelConfig(&ADC1_driver, i);
    }

    ADC_LLD_ConversionTiming(&ADC0_driver, ADC_CTR0_CH0_CH15, CTR_INPCMP_5, CTR_INPSAMP(60UL)); /* PRQA S 3469 */
    ADC_LLD_ConversionTiming(&ADC1_driver, ADC_CTR1_CH32_CH59, CTR_INPCMP_5, CTR_INPSAMP(60UL)); /* PRQA S 3469 */

    ADC_LLD_DMA_Enable(&ADC0_driver);
    ADC_LLD_DMA_Enable(&ADC1_driver);
    EdmaInit();
    EdmaChannelSetup_C(ADC_DMA_CHANNEL0,                /* channel.                 */
                (uint32_t)(&(ADC_0.CDR[0].R)),          /* src.   (uint32_t)(&(ADC_0.CDR[0].R))         */
                           (uint32_t)&case6_ADC0Buf[0], /* dst.                     */
                           4,                           /* soff, do not advance.    */
                           4,                           /* doff, advance by two.    */
                           2,                           /* ssize, 16 bits transfers.*/
                           2,                           /* dsize, 16 bits transfers.*/
                           4,                           /* nbytes, always two.      */
                           4,                           /* iter.                    */
                           - 16,                         /* slast, no source adjust. */
                           - 16,                         /* dlast.                   */
                           0);                          /* mode.    */

    EdmaChannelSetup_C(ADC_DMA_CHANNEL1,                /* channel.                 */
                (uint32_t)(&(ADC_1.CDR[32].R)),         /* src.   (uint32_t)(&(ADC_1.CDR[32].R))         */
                           (uint32_t)&case6_ADC1Buf[0], /* dst.                     */
                           4,                           /* soff, do not advance.    */
                           4,                           /* doff, advance by two.    */
                           2,                           /* ssize, 16 bits transfers.*/
                           2,                           /* dsize, 16 bits transfers.*/
                           4,                           /* nbytes, always two.      */
                           4,                           /* iter.                    */
                           - 16,                         /* slast, no source adjust. */
                           - 16,                         /* dlast.                   */
                           0);                          /* mode.    */

    EdmaChannelStart(ADC_DMA_CHANNEL0); /* PRQA S 3469 */
    EdmaChannelStart(ADC_DMA_CHANNEL1); /* PRQA S 3469 */
    DMAMUX_ChConfigEn(ADC_DMA_CHANNEL0, ADC0_TRIG_SOURCE);
    DMAMUX_ChConfigEn(ADC_DMA_CHANNEL1, ADC1_TRIG_SOURCE);
    delay_ms(300U);

    ADC_LLD_Start(&ADC0_driver);
    ADC_LLD_Start(&ADC1_driver);

    while (ADC_ECH_IntFlag(&ADC0_driver) != 1U)
    {
        ;
    }
    while (ADC_ECH_IntFlag(&ADC1_driver) != 1U)
    {
        ;
    }

    ADC_Stop(&ADC0_driver);
    ADC_Stop(&ADC1_driver);

    PSPRINTF("\n***********************\n");
    PSPRINTF("ADC_Test_Case6_DMA Start!\n");
    for (i = 0U; i < 4U; i++)
    {
        PSPRINTF("ADC0 Ch%d data = %d, = %dmV\n", i, \
                (case6_ADC0Buf[i]&ADC0_CDATA_MASK), \
                (case6_ADC0Buf[i]&ADC0_CDATA_MASK)*ADC_POWER_REF/0x3FFU);
    }
    for (i = 32U; i < 36U; i++)
    {
        PSPRINTF("ADC1 Ch%d data = %d, = %dmV\n", i, \
                (case6_ADC1Buf[i - 32U]&ADC1_CDATA_MASK), \
                (case6_ADC1Buf[i - 32U]&ADC1_CDATA_MASK)*ADC_POWER_REF/0xFFFU);
    }
    PSPRINTF("ADC_Test_Case6_DMA End!\n");
    PSPRINTF("***********************\n\n");
}

/*******************************************************************************
 * @brief      ADC Test Case7: ADC CTU trigger
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
#define CTU_PIT_3_SOURCE    23
#define CTU_PIT_CH          3
#define CTU_TRI_CH          1
static void ADC_Test_Case7_CTU(void)/* PRQA S 3219 */
{
    uint32_t i = 0;

    ADC0_driver.index = ADC0_SELECT;
    ADC1_driver.index = ADC1_SELECT;

    ADC_LLD_Cfg_Init(&ADC0_driver, &usr_oneshot_config);
    ADC_LLD_Cfg_Init(&ADC1_driver, &usr_oneshot_config);

    for (i = 0U; i < 4U; i++)
    {
        /* Ch0~Ch3 */
        ADC_LLD_ChannelConfig(&ADC0_driver, i);
    }
    for (i = 32U; i < 36U; i++)
    {
        /* Ch32~Ch35 */
        ADC_LLD_ChannelConfig(&ADC1_driver, i);
    }

    ADC_LLD_ConversionTiming(&ADC0_driver, ADC_CTR0_CH0_CH15, CTR_INPCMP_5, CTR_INPSAMP(60UL)); /* PRQA S 3469 */
    ADC_LLD_ConversionTiming(&ADC1_driver, ADC_CTR1_CH32_CH59, CTR_INPCMP_5, CTR_INPSAMP(60UL)); /* PRQA S 3469 */

    ADC_LLD_CTU_Enable(&ADC0_driver);

    /* pit config */
    PIT.CH[CTU_PIT_CH].LDVAL.R = 0xffff;
    PIT.CH[CTU_PIT_CH].TCTRL.B.TEN = 1;
    PIT.PITMCR.B.MDIS = 0;
    /* ctu config */
    CTU.EVTCFGR[CTU_PIT_3_SOURCE].B.ADC_SEL = 0;
    CTU.EVTCFGR[CTU_PIT_3_SOURCE].B.CHANNEL_VALUE = CTU_TRI_CH;
    CTU.EVTCFGR[CTU_PIT_3_SOURCE].B.TM = 1;

    delay_ms(300U);

    for (i = 0U; i < 4U; i++)
    {
        /* Ch0~Ch3 */
        case7_ADC0Buf[i] = ADC_LLD_ChanValue(&ADC0_driver, i);
    }
    for (i = 32U; i < 36U; i++)
    {
        /* Ch32~Ch35 */
        case7_ADC1Buf[i - 32U] = ADC_LLD_ChanValue(&ADC1_driver, i);
    }

    PSPRINTF("\n***********************\n");
    PSPRINTF("ADC_Test_Case7_CTU Start!\n");
    PSPRINTF("ADC0 Ch%d data = %d, = %dmV\n", CTU_TRI_CH, case7_ADC0Buf[CTU_TRI_CH], \
            case7_ADC0Buf[CTU_TRI_CH]*ADC_POWER_REF/0x3FFU);
    PSPRINTF("ADC_Test_Case7_CTU End!\n");
    PSPRINTF("***********************\n\n");
}

/*******************************************************************************
 * @brief      ADC_Test_Demo
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void ADC_Test_Demo(void)
{
    /* ADC0 Ch0~Ch3: PB[4], PB[5], PB[6], PB[7];
     * ADC1 Ch32~Ch35: PA[3], PA[7], PA[10], PA[11] */
	/* Function: ADC scan mode test */
#if ADC_CASE1  
    ADC_Test_Case1_ScanMode(ADC_POWER_REF);
#endif

    /* Function: ADC oneshot mode test  */
#if ADC_CASE2
    ADC_Test_Case2_OneshotMode(ADC_POWER_REF);
#endif

    /* Function: ADC ECH interrupt test */
#if ADC_CASE3
    ADC_Test_Case3_ECHInt();
#endif

    /* Function: ADC WDG interrupt test */
#if ADC_CASE4
    ADC_Test_Case4_WtgInt();
#endif

    /* Function: ADC Injected Mode test */
#if ADC_CASE5
    ADC_Test_Case5_InjectedMode();
#endif

    /* Function: ADC CTU trigger test */
#if ADC_CASE6
    ADC_Test_Case7_CTU();
#endif
}
